use crate::renderer::firework;

use firework::FireworkState;
use rand::{rngs::StdRng, Rng};

const COLORS: [PixelColor; 10] = [
  // blue
  PixelColor {
    r: 25,
    g: 25,
    b: 255,
  },
  // red
  PixelColor {
    r: 255,
    g: 51,
    b: 51,
  },
  PixelColor {
    // orange
    r: 255,
    g: 140,
    b: 25,
  },
  PixelColor {
    // yellow
    r: 255,
    g: 255,
    b: 0,
  },
  PixelColor {
    // g
    r: 0,
    g: 204,
    b: 0,
  },
  PixelColor {
    // teal
    r: 0,
    g: 170,
    b: 204,
  },
  PixelColor {
    // purple
    r: 179,
    g: 25,
    b: 255,
  },
  PixelColor {
    // pink
    r: 255,
    g: 51,
    b: 255,
  },
  PixelColor {
    // deep pink
    r: 255,
    g: 51,
    b: 119,
  },
  PixelColor {
    // r
    r: 255,
    g: 25,
    b: 64,
  },
];

#[derive(Debug)]
pub enum FireworkType {
  Simple(PixelColor),
  Rainbow([PixelColor; 5]),
}

impl FireworkType {
  pub fn derive_color(&self, state: FireworkState) -> PixelColor {
    match self {
      FireworkType::Simple(p) => *p,
      FireworkType::Rainbow(c) => c[state.ordinal() as usize],
    }
  }
}

pub fn pick_firework_type(rng: &mut StdRng) -> FireworkType {
  if rng.gen_range(0, 100) < 11 {
    gen_rainbow(rng)
  } else {
    gen_regular(rng)
  }
}

fn gen_rainbow(rng: &mut StdRng) -> FireworkType {
  let mut rainbow: [PixelColor; 5] = Default::default();
  let rand_color = PixelColor::pick_rand(rng);
  let start_idx = COLORS
    .iter()
    .position(|color| rand_color == *color)
    .unwrap_or(0);

  for (count, i) in (start_idx..start_idx + 5).enumerate() {
    rainbow[count] = COLORS[i % COLORS.len()];
  }

  FireworkType::Rainbow(rainbow)
}

fn gen_regular(rng: &mut StdRng) -> FireworkType {
  FireworkType::Simple(PixelColor::pick_rand(rng))
}

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct PixelColor {
  pub r: u8,
  pub g: u8,
  pub b: u8,
}

impl PixelColor {
  #[must_use]
  pub fn pick_rand(rng: &mut StdRng) -> PixelColor {
    COLORS[rng.gen_range(0, COLORS.len())]
  }
}
